package etrgo

import (
	"fmt"
	"html/template"
	"io"
	"io/ioutil"
	"os"
	"path"
	"path/filepath"
	"strings"
)

const (
	TEMPLATE_DIR = "views"
	TEMPLATE_EXT = ".htm"
)

var PathSeparator string

//var viewTemplates = map[string]*template.Template{}

type TemplateLoader struct {
	RootDir       string
	viewTemplates map[string]*template.Template //{}
}

// The functions available for use in the templates.
var templateFuncs = map[string]interface{}{
	"eq":       Equal,
	"gt":       Gt,
	"set":      Set,
	"append":   Append,
	"include":  Include,
	"time":     Time,
	"timestamp":Timestamp,
}

func init() {
	PathSeparator = fmt.Sprintf("%c", os.PathSeparator)
	//curPath, _ := os.Getwd()
	//dirPath := curPath + PathSeparator + TEMPLATE_DIR
	//loadDir(dirPath)
}
func (loader *TemplateLoader) init() {
	if loader.viewTemplates == nil {
		loader.viewTemplates = make(map[string]*template.Template)
	}
}

func (loader *TemplateLoader) LoadDir(dirPath string) {
	loader.init()
	filesInfo, err := ioutil.ReadDir(dirPath)

	Info("Loading the template directory: %s", dirPath)
	if err != nil {
		Critical("open the dir error[dir=%s,err=%s]", dirPath, err.Error())
		return
	}

	var templatePath string
	for _, fileInfo := range filesInfo {
		templateName := fileInfo.Name()
		if ext := path.Ext(templateName); ext != TEMPLATE_EXT {
			file, err := os.Stat(dirPath + PathSeparator + templateName)
			if err == nil && file.IsDir() {
				loader.LoadDir(dirPath + PathSeparator + templateName)
			}
			continue
		}
		templatePath = dirPath + PathSeparator + templateName
		Info("Loading template: %s", templatePath)

		tmplName := strings.Split(templateName, TEMPLATE_EXT)[0]

		t := template.New(templateName)
		t = t.Funcs(templateFuncs)
		t = template.Must(t.ParseFiles(templatePath))
		//t := template.Must(template.ParseFiles(templatePath))
		Info("Parse file :%s,name=%s", tmplName, t.Name())
		loader.viewTemplates[tmplName] = t
	}
}

func (loader *TemplateLoader) LoadFile(fileName string) {
	filebaseName := filepath.Base(fileName)
	tmplName := strings.Split(filebaseName, TEMPLATE_EXT)[0]
	t := template.New(filebaseName)
	t = t.Funcs(templateFuncs)
	t = template.Must(t.ParseFiles(fileName))
	Info("Parse file :%s,name=%s", tmplName, t.Name())
	loader.viewTemplates[tmplName] = t
}

func (loader *TemplateLoader) Lookup(name string) *template.Template {
	tmplName := strings.Split(name, TEMPLATE_EXT)[0]
	return loader.viewTemplates[tmplName]
}

func (loader *TemplateLoader) Render(view string, wr io.Writer, data interface{}) {
	tmpl := loader.viewTemplates[view]
	if tmpl != nil {
		err := tmpl.ExecuteTemplate(wr, tmpl.Name(), data)
		if err != nil {
			Error("failed to render the template[name=%s,err=%s]", view, err)
		}
	} else {
		Error("the template view not exist[view=%s]", view)
	}
}
